﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using Moq;
using System.Web.Routing;
using System.Web;

namespace MvcPatch.Routing.Test
{
    public class DomainRouteTest
    {
        [Fact]
        public void GetRouteData()
        {
            var routeData = new RouteData();
            routeData.Values.Add("controller", "Home");
            routeData.Values.Add("action", "Index");

            Mock<HttpRequestWrapper> mockRequest;
            var mockHttpContext = HttpMocker.MockRequest("http://blogs.cnblogs.com/aaa/bbb/ccc", out mockRequest);

            var mockInnerRoute = new Mock<RouteBase>();
            mockInnerRoute.Setup(r => r.GetRouteData(mockHttpContext.Object)).Returns(routeData);

            var domainRoute = new DomainRoute(mockInnerRoute.Object, "http://{area}.{*domain}", null, null);
            var domainRouteData = domainRoute.GetRouteData(mockHttpContext.Object);

            Assert.Equal("Home", routeData.GetRequiredString("controller"));
            Assert.Equal("Index", routeData.GetRequiredString("action"));
            Assert.Equal("blogs", routeData.GetRequiredString("area"));
            Assert.Equal("cnblogs.com", routeData.GetRequiredString("domain"));

            Assert.Equal(4, routeData.Values.Count);
        }

        [Fact]
        public void GetRouteData_but_Failed()
        {
            Mock<HttpRequestWrapper> mockRequest;
            var mockHttpContext = HttpMocker.MockRequest("http://blogs.cnblogs.com/", out mockRequest);

            var mockInnerRoute = new Mock<RouteBase>();
            mockInnerRoute.Setup(r => r.GetRouteData(mockHttpContext.Object)).Returns(new RouteData());

            var domainRoute = new DomainRoute(mockInnerRoute.Object, "http://www.{*domain}", null, null);
            var domainRouteData = domainRoute.GetRouteData(mockHttpContext.Object);

            Assert.Null(domainRouteData);
        }

        [Fact]
        public void GetRouteData_with_Defaults()
        {
            var routeData = new RouteData();
            routeData.Values.Add("controller", "Home");
            routeData.Values.Add("action", "Index");

            Mock<HttpRequestWrapper> mockRequest;
            var mockHttpContext = HttpMocker.MockRequest("http://www.cnblogs.com/", out mockRequest);

            var mockInnerRoute = new Mock<RouteBase>();
            mockInnerRoute.Setup(r => r.GetRouteData(mockHttpContext.Object)).Returns(routeData);

            var defaults = new RouteValueDictionary();
            defaults.Add("area", "clients");

            var domainRoute = new DomainRoute(mockInnerRoute.Object, "http://www.{*domain}", defaults, null);
            var domainRouteData = domainRoute.GetRouteData(mockHttpContext.Object);

            Assert.Equal("Home", routeData.GetRequiredString("controller"));
            Assert.Equal("Index", routeData.GetRequiredString("action"));
            Assert.Equal("clients", routeData.GetRequiredString("area"));
            Assert.Equal("cnblogs.com", routeData.GetRequiredString("domain"));

            Assert.Equal(4, routeData.Values.Count);
        }

        [Fact]
        public void GetRouteData_with_Constraints_but_Failed()
        {
            var routeData = new RouteData();
            routeData.Values.Add("controller", "Home");
            routeData.Values.Add("action", "Index");

            Mock<HttpRequestWrapper> mockRequest;
            var mockHttpContext = HttpMocker.MockRequest("http://www.cnblogs.com/", out mockRequest);

            var mockInnerRoute = new Mock<RouteBase>();
            mockInnerRoute.Setup(r => r.GetRouteData(mockHttpContext.Object)).Returns(routeData);

            var constraints = new RouteValueDictionary();
            constraints.Add("area", "blogs");

            var domainRoute = new DomainRoute(mockInnerRoute.Object, "http://{area}.{*domain}", null, constraints);
            var domainRouteData = domainRoute.GetRouteData(mockHttpContext.Object);

            Assert.Null(domainRouteData);
        }
    }
}
